/*
 * Copyright (C) 2022, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * Authors: iaom <zhangpengfei@kylinos.cn>
 *
 */
#include "bluetooth-shortcut.h"

#include <QDebug>
#include <QDBusReply>
#include <QMutexLocker>
#include <QTranslator>
#include <QApplication>

#define BLUETOOTH_ACTIVE_SYMBOLIC "bluetooth-active-symbolic"

using namespace UkuiShortcut;
BluetoothShortcut::BluetoothShortcut()
{
    QTranslator *translator = new QTranslator(this);
    try {
        if(!translator->load(QString(TRANSLATION_FILE_DIR) + "/bluetooth-shortcut_" + QLocale::system().name() + ".qm")) throw -1;
        QApplication::installTranslator(translator);
    } catch(...) {
        qWarning() << "BluetoothShortcut load translations file" << QLocale::system().name() << "failed!";
    }
    m_statusInfo.setIcon(BLUETOOTH_ACTIVE_SYMBOLIC);
    m_statusInfo.setColor(Color::Danger);
    m_statusInfo.setName(tr("Bluetooth"));
    m_statusInfo.setToolTip(tr("Bluetooth"));

    initMetaData();

    m_connector = new BluetoothConnector(this);
    connect(m_connector, &BluetoothConnector::ready, this, &BluetoothShortcut::init);
    connect(m_connector, &BluetoothConnector::failed, this, &BluetoothShortcut::connectionFailed);
    m_connector->start();
}

void BluetoothShortcut::active(PluginMetaType::Action action)
{
    QMutexLocker locker(&m_mutex);
    if(!m_bluetoothIface) {
        return;
    }
    QDBusReply<bool> reply;
    switch (action) {
    case PluginMetaType::Action::Click:
        reply = m_bluetoothIface->call("setDefaultAdapterPower", !m_defaultAdapterPower);
        if(!reply.isValid()) {
            qWarning() << "BluetoothShortcut call " << "setDefaultAdapterPower" << "failed";
        }
        break;
    case PluginMetaType::Action::MenuRequest:
        reply = m_bluetoothIface->call("showTrayWidgetUI");
        if(!reply.isValid()) {
            qWarning() << "BluetoothShortcut call " << "showTrayWidgetUI" << "failed";
        }
        break;
    default:
        break;
    }
}

const StatusInfo BluetoothShortcut::currentStatus()
{
    QMutexLocker locker(&m_mutex);
    return m_statusInfo;
}

bool BluetoothShortcut::isEnable()
{
    return m_isEnable;
}

void BluetoothShortcut::init(QDBusInterface *interface)
{
    m_mutex.lock();
    m_bluetoothIface = interface;
    m_bluetoothIface->setParent(this);

    QDBusMessage reply = m_bluetoothIface->call("getAdapterDevAddressList");
    QList<QVariant> outArgs = reply.arguments();
    QStringList adapterList;
    if (!outArgs.isEmpty()) {
        QVariant first = outArgs.at(0);
        if (first.isValid()) {
            adapterList = first.toStringList();
        }
    }
    QDBusReply<bool> state = m_bluetoothIface->call("getDefaultAdapterPower");
    if(state.isValid()) {
        if(!adapterList.isEmpty()) {
            m_defaultAdapterPower = state.value();
            m_statusInfo.setColor(m_defaultAdapterPower? Color::ColorRole::HighLight : Color::ColorRole::BaseColor);
            m_isEnable = true;
        } else {
            m_isEnable = false;
        }
    } else {
        m_isEnable = false;
        m_mutex.unlock();
        return;
    }

    updateData();
    if(!QDBusConnection::sessionBus().connect(BLUETOOTH_SERVICE_NAME,
                                              BLUETOOTH_SERVICE_PATH,
                                              BLUETOOTH_SERVICE_INTERFACE,
                                              "defaultAdapterPowerChanged",
                                              this,
                                              SLOT(defaultAdapterPowerChangedSlot(bool)))) {
        qWarning() << "BluetoothShortcut connect " << "defaultAdapterPowerChanged" << "failed";
    }

    if(!QDBusConnection::sessionBus().connect(BLUETOOTH_SERVICE_NAME,
                                              BLUETOOTH_SERVICE_PATH,
                                              BLUETOOTH_SERVICE_INTERFACE,
                                              "devConnectStatusSignal",
                                              this,
                                              SLOT(devConnectStatusSlot(QString, bool)))) {
        qWarning() << "BluetoothShortcut connect " << "devConnectStatusSignal" << "failed";
    }
    if(!QDBusConnection::sessionBus().connect(BLUETOOTH_SERVICE_NAME,
                                          BLUETOOTH_SERVICE_PATH,
                                          BLUETOOTH_SERVICE_INTERFACE,
                                          "devRemoveSignal",
                                          this,
                                          SLOT(devRemoveSlot(QString)))) {
        qWarning() << "BluetoothShortcut connect " << "devRemoveSignal" << "failed";
    }
    if(!QDBusConnection::sessionBus().connect(BLUETOOTH_SERVICE_NAME,
                                             BLUETOOTH_SERVICE_PATH,
                                             BLUETOOTH_SERVICE_INTERFACE,
                                             "adapterRemoveSignal",
                                             this,
                                             SLOT(updateState()))) {
        qWarning() << "BluetoothShortcut connect " << "adapterRemoveSignal" << "failed";
    }
    if(!QDBusConnection::sessionBus().connect(BLUETOOTH_SERVICE_NAME,
                                             BLUETOOTH_SERVICE_PATH,
                                             BLUETOOTH_SERVICE_INTERFACE,
                                             "adapterAddSignal",
                                             this,
                                             SLOT(updateState()))) {
        qWarning() << "BluetoothShortcut connect " << "adapterAddSignal" << "failed";
    }

    m_statusInfo.setIcon(BLUETOOTH_ACTIVE_SYMBOLIC);
    m_mutex.unlock();
    Q_EMIT enableStatusChanged(m_isEnable);
}

void BluetoothShortcut::connectionFailed()
{
    m_isEnable = false;
}

void BluetoothShortcut::defaultAdapterPowerChangedSlot(bool status)
{
    qDebug() << "BluetoothShortcut: defaultAdapterPowerChanged: " <<status;
    m_defaultAdapterPower = status;
    m_statusInfo.setColor(status? Color::ColorRole::HighLight: Color::ColorRole::BaseColor);
    Q_EMIT statusChanged(m_statusInfo);
}

void BluetoothShortcut::devConnectStatusSlot(QString name, bool status)
{
    Q_UNUSED(name)
    Q_UNUSED(status)
    updateData();
    Q_EMIT statusChanged(m_statusInfo);
}

void BluetoothShortcut::devRemoveSlot(QString name)
{
    Q_UNUSED(name)
    updateData();
    Q_EMIT statusChanged(m_statusInfo);
}

void BluetoothShortcut::updateData()
{
    if(!m_bluetoothIface) {
        return;
    }

    QDBusReply<QStringList> replylist = m_bluetoothIface->call("getDefaultAdapterPairedDevAddress");
    if (replylist.isValid()) {
        QStringList addressList = replylist.value();
        QString displayName;
//        qDebug()<<"bluetooth address list:" << addressList;
        for(QString address : addressList) {
            QDBusReply<bool> statusReply = m_bluetoothIface->call("getDevConnectStatus",address);
            if(statusReply.isValid()) {
                if(statusReply.value()) {
                    QDBusReply<QString> devName = m_bluetoothIface->call("getDevName",address);
                    if(devName.isValid()) {
                        displayName.append(devName.value());
                    }
                }
            }
        }
        if(displayName.isEmpty()) {
            m_statusInfo.setName(tr("No Connection"));
        } else {
            m_statusInfo.setName(displayName);
        }
    }
}

QMap<PluginMetaType::SystemMode, PluginMetaData> BluetoothShortcut::pluginMetaData()
{
    return m_metaData;
}

void BluetoothShortcut::initMetaData()
{
    PluginMetaData pc {true, 1, PluginMetaType::PluginType::Icon};
    PluginMetaData tablet {true, 1, PluginMetaType::PluginType::MenuButton};
    m_metaData.insert(PluginMetaType::SystemMode::PC, pc);
    m_metaData.insert(PluginMetaType::SystemMode::Tablet, tablet);
}

void BluetoothShortcut::updateState()
{
    if(!m_bluetoothIface) {
        return;
    }

    QDBusMessage reply = m_bluetoothIface->call("getAdapterDevAddressList");
    QStringList adapterList;
    QList<QVariant> outArgs = reply.arguments();
    if (!outArgs.isEmpty()) {
        QVariant first = outArgs.at(0);
        if (first.isValid()) {
            adapterList = first.toStringList();
        }
    }

    if (!adapterList.isEmpty()) {
        m_isEnable = true;
        updateData();
    }
    else {
        m_isEnable = false;
    }
    Q_EMIT enableStatusChanged(m_isEnable);
}
